﻿using System;
using System.Runtime.Serialization;
using System.Runtime.InteropServices;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Text;

namespace GLLog.Comms
{
    public class Comms
    {
        public static string GetIP()
        {
            try
            {
                string result = "";
                string HostName = Dns.GetHostName();
                IPHostEntry IpEntry = Dns.GetHostEntry(HostName);
                for (int i = 0; i < IpEntry.AddressList.Length; i++)
                {
                    if (IpEntry.AddressList[i].AddressFamily == AddressFamily.InterNetwork)
                    {
                        result += IpEntry.AddressList[i].ToString() + " ; ";
                    }
                }
                result = result.Substring(0, result.Length - 2);
                return result;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        public static string GetServerIP()
        {
            try
            {
                string result = "";
                string HostName = Dns.GetHostName();
                IPHostEntry IpEntry = Dns.GetHostEntry(HostName);
                for (int i = 0; i < IpEntry.AddressList.Length; i++)
                {
                    if (IpEntry.AddressList[i].AddressFamily == AddressFamily.InterNetwork)
                    {
                        result = IpEntry.AddressList[i].ToString();
                        break;
                    }
                }
                return result;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        ///  <summary>  
        ///  对象序列化为二进制字节数组  
        ///  </summary>  
        ///  <param  name="request">要序列化的对象 </param>  
        ///  <returns>字节数组 </returns>  
        public byte[] SerializeBinary(List<GLLog.DataEntity.CliErrEntity> ee)
        {
            IFormatter formatter = new BinaryFormatter();
            MemoryStream stream = new MemoryStream();
            formatter.Serialize(stream, ee);
            stream.Position = 0;
            byte[] buffer = new byte[stream.Length];
            stream.Read(buffer, 0, buffer.Length);
            stream.Flush();
            stream.Close();
            return buffer;
        }

        ///  <summary>  
        ///  从二进制数组反序列化得到对象  
        ///  </summary>  
        ///  <param  name="buf">字节数组 </param>  
        ///  <returns>得到的对象 </returns>  
        public List<GLLog.DataEntity.CliErrEntity> DeserializeBinary(byte[] buf)
        {
            MemoryStream memStream = new MemoryStream(buf);
            memStream.Position = 0;
            IFormatter deserializer = new BinaryFormatter();
            List<GLLog.DataEntity.CliErrEntity> ee = (List<GLLog.DataEntity.CliErrEntity>)deserializer.Deserialize(memStream);
            memStream.Close();
            return ee;
        }

        ///  <summary>  
        ///  对象序列化为二进制字节数组  
        ///  </summary>  
        ///  <param  name="request">要序列化的对象 </param>  
        ///  <returns>字节数组 </returns>  
        public byte[] SvrSerializeBinary(List<GLLog.DataEntity.SvrErrEntity> se)
        {
            IFormatter formatter = new BinaryFormatter();
            MemoryStream stream = new MemoryStream();
            formatter.Serialize(stream, se);
            stream.Position = 0;
            byte[] buffer = new byte[stream.Length];
            stream.Read(buffer, 0, buffer.Length);
            stream.Flush();
            stream.Close();
            return buffer;
        }

        ///  <summary>  
        ///  从二进制数组反序列化得到对象  
        ///  </summary>  
        ///  <param  name="buf">字节数组 </param>  
        ///  <returns>得到的对象 </returns>  
        public List<GLLog.DataEntity.SvrErrEntity> SvrDeserializeBinary(byte[] buf)
        {
            MemoryStream memStream = new MemoryStream(buf);
            memStream.Position = 0;
            IFormatter deserializer = new BinaryFormatter();
            List<GLLog.DataEntity.SvrErrEntity> se = (List<GLLog.DataEntity.SvrErrEntity>)deserializer.Deserialize(memStream);
            memStream.Close();
            return se;
        }

        #region RC4加密算法
        private static Encoding Encode = Encoding.Default;
        public Byte[] EncryptEx(Byte[] data, String pass)
        {
            if (data == null || pass == null) return null;
            Byte[] output = new Byte[data.Length];
            Int64 i = 0;
            Int64 j = 0;
            Byte[] mBox = GetKey(Encode.GetBytes(pass), 256);

            // 加密
            for (Int64 offset = 0; offset < data.Length; offset++)
            {
                i = (i + 1) % mBox.Length;
                j = (j + mBox[i]) % mBox.Length;
                Byte temp = mBox[i];
                mBox[i] = mBox[j];
                mBox[j] = temp;
                Byte a = data[offset];
                //Byte b = mBox[(mBox[i] + mBox[j] % mBox.Length) % mBox.Length];
                // mBox[j] 一定比 mBox.Length 小，不需要在取模
                Byte b = mBox[(mBox[i] + mBox[j]) % mBox.Length];
                output[offset] = (Byte)((Int32)a ^ (Int32)b);
            }

            return output;
        }

        public Byte[] DecryptEx(Byte[] data, String pass)
        {
            return EncryptEx(data, pass);
        }

        /// <summary>
        /// 打乱密码
        /// </summary>
        /// <param name="pass">密码</param>
        /// <param name="kLen">密码箱长度</param>
        /// <returns>打乱后的密码</returns>
        static private Byte[] GetKey(Byte[] pass, Int32 kLen)
        {
            Byte[] mBox = new Byte[kLen];

            for (Int64 i = 0; i < kLen; i++)
            {
                mBox[i] = (Byte)i;
            }
            Int64 j = 0;
            for (Int64 i = 0; i < kLen; i++)
            {
                j = (j + mBox[i] + pass[i % pass.Length]) % kLen;
                Byte temp = mBox[i];
                mBox[i] = mBox[j];
                mBox[j] = temp;
            }
            return mBox;
        }
        #endregion
    }
}
